var SmartNode = function (option) {
    this._init(option);
}
SmartNode.prototype = {
    _init: function (option) {
        this.r = option.r ||12;
        this.data = option.data || [];
        this.mLeft = option.mLeft || 5 * this.r;
        this.space = option.space ||8 * this.r;
        this.angle = 3 * this.r;
        this.nodeArr = [];
        this.hoverColor = "#c9302c";
    },
    drawDashLine: function (ctx, x1, y1, x2, y2, dashLength) {
        var dashLen = dashLength === undefined ? 5 : dashLength,
            xpos = x2 - x1,
            ypos = y2 - y1,
            numDashes = Math.floor(Math.sqrt(xpos * xpos + ypos * ypos) / dashLen);
        for (var i = 0; i < numDashes; i++) {
            if (i % 2 === 0) {
                ctx.moveTo(x1 + (xpos / numDashes) * i, y1 + (ypos / numDashes) * i);
            } else {
                ctx.lineTo(x1 + (xpos / numDashes) * i, y1 + (ypos / numDashes) * i);
            }
        }
        ctx.stroke();
    },
    render: function (canvas) {
        var this_ = this;
        this_.canvas = canvas;
        var ctx = canvas.getContext("2d");
        this_.ctx = ctx;
        var x = this_.mLeft;
        var y = canvas.height / 2;
        this_.data.forEach(function (item, index) {
            if (!(item instanceof Array)) {
                x = index == 0 ? x : (x + this_.space);
                if ((index - 1) >= 0 && this_.data[index - 1] instanceof Array) {
                    var arr = this_.data[index - 1];
                    if (arr.length % 2 == 0) {
                        var itemY = this_.angle;
                        for (var i = 0; i < arr.length / 2; i++) {
                            this_.drawDashLine(ctx, x - this_.space - this_.r + this_.r * Math.sin((90 - itemY) * Math.PI / 180), y - Math.tan(itemY * Math.PI / 180) * this_.space + this_.r * Math.cos((90 - itemY) * Math.PI / 180), x, y, 2);
                            itemY = itemY + this_.angle;
                        }
                        var itemY = this_.angle;
                        for (var i = 0; i < arr.length / 2; i++) {
                            this_.drawDashLine(ctx, x - this_.space - this_.r + this_.r * Math.sin((90 - itemY) * Math.PI / 180), y + Math.tan(itemY * Math.PI / 180) * this_.space - this_.r * Math.cos((90 - itemY) * Math.PI / 180), x, y, 2);
                            itemY = itemY + this_.angle;
                        }
                    } else {
                        var itemY = 0;
                        for (var i = 0; i < parseInt(arr.length / 2) + 1; i++) {
                            this_.drawDashLine(ctx, x - this_.space - this_.r + this_.r * Math.sin((90 - itemY) * Math.PI / 180), y - Math.tan(itemY * Math.PI / 180) * this_.space + this_.r * Math.cos((90 - itemY) * Math.PI / 180), x, y, 2);
                            itemY = itemY + this_.angle;
                        }
                        var itemY = this_.angle;
                        for (var i = 0; i < parseInt(arr.length / 2); i++) {
                            this_.drawDashLine(ctx, x - this_.space - this_.r + this_.r * Math.sin((90 - itemY) * Math.PI / 180), y + Math.tan(itemY * Math.PI / 180) * this_.space - this_.r * Math.cos((90 - itemY) * Math.PI / 180), x, y, 2);
                            itemY = itemY + this_.angle;
                        }
                    }
                }
                if (index == 0) {
                    ctx.moveTo(x, y);
                    x = x + this_.space;
                }
                if (!((index - 1) >= 0 && this_.data[index - 1] instanceof Array)) {
                    this_.drawDashLine(ctx, x - this_.space, y, x, y, 2);
                }
                ctx.moveTo(x + 2 * this_.r, y);
                ctx.arc(x + this_.r, y, this_.r, 0, 2 * Math.PI);
                this_.nodeArr.push({
                    x: x + this_.r,
                    y: y,
                    data: item
                });
                ctx.fillStyle = item.color || "orange";
                ctx.fill();
                ctx.textAlign = "center";
                ctx.textBaseline = "middle";
                ctx.font = "bold 14px Arial";
                ctx.fillStyle = "#36abd8";
                ctx.strokeStyle = "silver";
                ctx.fillText(item.note, x + this_.r, y - this_.r - 20);
                ctx.fillStyle = "black";
                ctx.fillText(item.title, x + this_.r, y + this_.r + 20);
                x = x + 2 * this_.r;
                if (index == (this_.data.length - 1)) {
                    this_.drawDashLine(ctx, x, y, x + this_.space, y, 2);
                    ctx.moveTo(x + this_.space, y);
                    ctx.lineTo(x + this_.space - this_.r, y - this_.r);
                    ctx.moveTo(x + this_.space, y);
                    ctx.lineTo(x + this_.space - this_.r, y + this_.r);
                }
                ctx.stroke();
                ctx.beginPath();
                ctx.moveTo(x, y);
            } else {
                if (!(this_.data[index - 1] instanceof Array)) {
                    var itemY = 0;
                    if (item.length % 2 == 0) {
                        itemY = this_.angle;
                        var dataArr = item.slice(0, item.length / 2).reverse();
                        for (var i = 0; i < dataArr.length; i++) {
                            this_.drawDashLine(ctx, x, y, x + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space, y - Math.tan(itemY * Math.PI / 180) * (this_.space), this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space,
                                y: y - Math.tan(itemY * Math.PI / 180) * (this_.space),
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            if (i == 0) {
                                ctx.fillStyle = "black";
                                ctx.fillText(dataArr[i].title, x + this_.space, y);
                            }
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space, y - Math.tan(itemY * Math.PI / 180) * (this_.space) - this_.r - 20);
                            ctx.fill();
                            ctx.moveTo(x + this_.r, y);
                            itemY = itemY + this_.angle;
                        }
                        itemY = this_.angle;
                        var dataArr = item.slice(item.length / 2, item.length);
                        for (var i = 0; i < dataArr.length; i++) {
                            this_.drawDashLine(ctx, x, y, x + this_.space, y + Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space, y + Math.tan(itemY * Math.PI / 180) * (this_.space), this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space,
                                y: y + Math.tan(itemY * Math.PI / 180) * (this_.space),
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space, y + Math.tan(itemY * Math.PI / 180) * (this_.space) + this_.r + 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                    } else {
                        var dataArr = item.slice(0, parseInt(item.length / 2) + 1).reverse();
                        for (var i = 0; i < dataArr.length; i++) {
                            this_.drawDashLine(ctx, x, y, x + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space, this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space,
                                y: y - Math.tan(itemY * Math.PI / 180) * this_.space,
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            if (i == 0) {
                                ctx.fillStyle = "black";
                                ctx.fillText(dataArr[i].title, x + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space + this_.r + 20);
                            }
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space - this_.r - 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                        itemY = this_.angle;
                        var dataArr = item.slice(parseInt(item.length / 2) + 1, item.length);
                        for (var i = 0; i < dataArr.length; i++) {
                            this_.drawDashLine(ctx, x, y, x + this_.space, y + Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space, y + Math.tan(itemY * Math.PI / 180) * this_.space, this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space,
                                y: y + Math.tan(itemY * Math.PI / 180) * this_.space,
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space, y + Math.tan(itemY * Math.PI / 180) * this_.space + this_.r + 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                    }
                    ctx.stroke();
                    ctx.beginPath();
                    x = x + this_.space + this_.r;
                    ctx.moveTo(x, y);
                } else {
                    if (item.length % 2 == 0) {
                        var itemY = this_.angle;
                        var dataArr = item.slice(0, item.length / 2).reverse();
                        for (var i = 0; i < dataArr.length; i++) {
                            ctx.moveTo(x, y - Math.tan(itemY * Math.PI / 180) * this_.space);
                            this_.drawDashLine(ctx, x, y - Math.tan(itemY * Math.PI / 180) * this_.space, x + this_.r + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space + this_.r, y - Math.tan(itemY * Math.PI / 180) * this_.space, this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space + this_.r,
                                y: y - Math.tan(itemY * Math.PI / 180) * this_.space,
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            if (i == 0) {
                                ctx.fillStyle = "black";
                                ctx.fillText(dataArr[i].title, x + this_.space + this_.r, y);
                            }
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space + this_.r, y - Math.tan(itemY * Math.PI / 180) * this_.space - this_.r - 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                        var itemY = this_.angle;
                        var dataArr = item.slice(item.length / 2, item.length);
                        for (var i = 0; i < dataArr.length; i++) {
                            ctx.moveTo(x, y + Math.tan(itemY * Math.PI / 180) * this_.space);
                            this_.drawDashLine(ctx, x, y + Math.tan(itemY * Math.PI / 180) * this_.space, x + this_.r + this_.space, y + Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space + this_.r, y + Math.tan(itemY * Math.PI / 180) * this_.space, this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space + this_.r,
                                y: y + Math.tan(itemY * Math.PI / 180) * this_.space,
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space + this_.r, y + Math.tan(itemY * Math.PI / 180) * this_.space + this_.r + 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                    } else {
                        var itemY = 0;
                        var dataArr = item.slice(0, parseInt(item.length / 2) + 1).reverse();
                        for (var i = 0; i < dataArr.length; i++) {
                            ctx.moveTo(x, y - Math.tan(itemY * Math.PI / 180) * this_.space);
                            this_.drawDashLine(ctx, x, y - Math.tan(itemY * Math.PI / 180) * this_.space, x + this_.r + this_.space, y - Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space + this_.r, y - Math.tan(itemY * Math.PI / 180) * this_.space, this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space + this_.r,
                                y: y - Math.tan(itemY * Math.PI / 180) * this_.space,
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            if (i == 0) {
                                ctx.fillStyle = "black";
                                ctx.fillText(dataArr[i].title, x + this_.space + this_.r, y - Math.tan(itemY * Math.PI / 180) * this_.space + this_.r + 20);
                            }
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space + this_.r, y - Math.tan(itemY * Math.PI / 180) * this_.space - this_.r - 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                        var itemY = this_.angle;
                        var dataArr = item.slice(parseInt(item.length / 2) + 1, item.length);
                        for (var i = 0; i < dataArr.length; i++) {
                            ctx.moveTo(x, y + Math.tan(itemY * Math.PI / 180) * this_.space);
                            this_.drawDashLine(ctx, x, y + Math.tan(itemY * Math.PI / 180) * this_.space, x + this_.r + this_.space, y + Math.tan(itemY * Math.PI / 180) * this_.space, 2);
                            ctx.beginPath();
                            ctx.arc(x + this_.space + this_.r, y + Math.tan(itemY * Math.PI / 180) * this_.space, this_.r, 0, 2 * Math.PI);
                            this_.nodeArr.push({
                                x: x + this_.space + this_.r,
                                y: y + Math.tan(itemY * Math.PI / 180) * this_.space,
                                data: dataArr[i]
                            });
                            ctx.textAlign = "center";
                            ctx.textBaseline = "middle";
                            ctx.font = "bold 14px Arial";
                            ctx.fillStyle = dataArr[i].color || "orange";
                            ctx.strokeStyle = "silver";
                            ctx.fill();
                            ctx.stroke();
                            ctx.beginPath();
                            ctx.fillStyle = dataArr[i].noteColor;
                            ctx.fillText(dataArr[i].note, x + this_.space + this_.r, y + Math.tan(itemY * Math.PI / 180) * this_.space + this_.r + 20);
                            ctx.fill();
                            itemY = itemY + this_.angle;
                        }
                    }
                    ctx.stroke();
                    ctx.beginPath();
                    x = x + this_.space + 2 * this_.r;
                    ctx.moveTo(x, y);
                }
            }
        });
        this_.showRemark();
        this_.onHover();
    },
    getMaxTextLength: function (arr) {
        var this_ = this;
        var max = this_.ctx.measureText(arr[0]['name'] + '熊').width;
        for (var i = 1; i < arr.length; i++) {
            if (this_.ctx.measureText(arr[i]['name'] + '熊').width > max) {
                max = this_.ctx.measureText(arr[i]['name'] + '熊').width;
            }
        }
        return max;
    },
    showRemark: function () {
        var this_ = this;
        for (var i = 0; i < this_.data.length; i++) {
            if (this_.data[i] instanceof Array) {
                var item = this_.data[i].reverse();
                var height = this_.canvas.height - 2 * this_.r;
                for (var j = 0; j < item.length; j++) {
                    this_.ctx.beginPath();
                    this_.ctx.font = "bold 12px Arial";
                    this_.ctx.fillStyle = "black";
                    this_.ctx.strokeStyle = item[j].noteColor;
                    this_.ctx.textAlign = "start";
                    this_.ctx.fillText(item[j].name + '熊', this_.mLeft, height);
                    this_.ctx.lineWidth = 3;
                    this_.drawDashLine(this_.ctx, this_.getMaxTextLength(item) + this_.mLeft, height, this_.getMaxTextLength(item) + this_.mLeft + this_.space, height, 2);
                    this_.ctx.stroke();
                    height = height - 2 * this_.r;
                }
                break;
            }
        }
    },
    getMousePos: function (canvas, evt) {
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left * (canvas.width / rect.width),
            y: evt.clientY - rect.top * (canvas.height / rect.height)
        }
    },
    clearCircle: function (ctx, x, y, r) {
        for (var i = 0; i < Math.round(Math.PI * r); i++) {
            var angle = (i / Math.round(Math.PI * r)) * 360;
            ctx.clearRect(x, y, Math.sin(angle * (Math.PI / 180)) * r, Math.cos(angle * (Math.PI / 180)) * r);
        }
    },
    onClick: function (callBack) {
        var this_ = this;
        var f = function (evt) {
            var mousePos = this_.getMousePos(this_.canvas, evt);
            var mouseX = mousePos.x;
            var mouseY = mousePos.y;
            this_.nodeArr.forEach(function (node, i) {
                if (mouseX >= (node.x - this_.r) && mouseX <= (node.x + this_.r) && mouseY >= (node.y - this_.r) && mouseY <= (node.y + this_.r)) {
                    callBack(node);
                }
            });
        }
        this_.canvas.removeEventListener('click', f);
        this_.canvas.addEventListener("click", f);
    },
    onHover: function () {
        var this_ = this;
        var f = function (evt) {
            var mousePos = this_.getMousePos(this_.canvas, evt);
            var mouseX = mousePos.x;
            var mouseY = mousePos.y;
            this_.nodeArr.forEach(function (node, i) {
                if (mouseX >= (node.x - this_.r) && mouseX <= (node.x + this_.r) && mouseY >= (node.y - this_.r) && mouseY <= (node.y + this_.r)) {
                    this_.ctx.beginPath();
                    this_.ctx.fillStyle = this_.hoverColor;
                    this_.ctx.arc(node.x, node.y, this_.r, 0, 2 * Math.PI);
                    this_.ctx.closePath();
                    this_.ctx.fill();
                    this_.ctx.lineWidth = 1;
                    this_.ctx.strokeStyle = "silver";
                    this_.ctx.stroke();
                } else {
                    this_.ctx.beginPath();
                    this_.ctx.fillStyle = node.data.color;
                    this_.ctx.arc(node.x, node.y, this_.r, 0, 2 * Math.PI);
                    this_.ctx.closePath();
                    this_.ctx.fill();
                    this_.ctx.lineWidth = 1;
                    this_.ctx.strokeStyle = "silver";
                    this_.ctx.stroke();
                }
            });
        }
        this_.canvas.removeEventListener('mousemove', f);
        this_.canvas.addEventListener("mousemove", f);
    }
}